<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>内存管理</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="spi-spi-getnspname.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="spi.html">快退</a></td><td width="60%" align="center" valign="bottom">章41. 服务器编程接口</td><td width="10%" align="right" valign="top"><a href="spi.html">快进</a></td><td width="10%" align="right" valign="top"><a href="spi-spi-palloc.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="SPI-MEMORY">41.3. 内存管理</a></h1>
<div>
<dl>
<dt><b>目录</b></dt>
<dt><a href="spi-spi-palloc.html">SPI_palloc</a>&nbsp;--&nbsp;在上层执行器环境里分配内存</dt>
<dt><a href="spi-realloc.html">SPI_repalloc</a>&nbsp;--&nbsp;在上层执行器环境里重新分配内存</dt>
<dt><a href="spi-spi-pfree.html">SPI_pfree</a>&nbsp;--&nbsp;在上层执行器环境里释放内存</dt>
<dt><a href="spi-spi-copytuple.html">SPI_copytuple</a>&nbsp;--&nbsp;在上层执行者环境里制作一个行的拷贝</dt>
<dt><a href="spi-spi-returntuple.html">SPI_returntuple</a>&nbsp;--&nbsp;准备把一个行当作 Datum 返回</dt>
<dt><a href="spi-spi-modifytuple.html">SPI_modifytuple</a>&nbsp;--&nbsp;通过替换一个给出行的选定的字段创建一行</dt>
<dt><a href="spi-spi-freetuple.html">SPI_freetuple</a>&nbsp;--&nbsp;释放在上层执行者环境里分配的一行</dt>
<dt><a href="spi-spi-freetupletable.html">SPI_freetuptable</a>&nbsp;--&nbsp;释放一个由 <code class="FUNCTION">SPI_execute</code> 或者类似函数创建的行集</dt>
<dt><a href="spi-spi-freeplan.html">SPI_freeplan</a>&nbsp;--&nbsp;释放一个前面保存的规划</dt>
</dl>
</div>
<p>PostgreSQL 在<i class="FIRSTTERM">内存环境</i>中分配内存，它提供了在许多地方分配的，有着不同的生命期的许多内存块的一个方便的管理方法。删除一个环境则释放所有在其内部分配的内存。因此，没必要跟踪独立的对象以避免内存泄漏；而是只要管理少量的环境。<code class="FUNCTION">palloc</code> 和相关的函数从"当前"的环境中分配内存。</p>
<p><code class="FUNCTION">SPI_connect</code> 创建一个新的内存环境并且将其标记为当前的环境。<code class="FUNCTION">SPI_finish</code> 恢复前一个内存环境并且删除 <code class="FUNCTION">SPI_connect</code> 创建的环境。这些动作确保在你的过程中分配的临时内存在过程结尾的时候都被回收，避免内存泄漏。</p>
<p>不过，如果你的过程需要返回一个已分配的内存对象(比如一个传递引用的数据类型)，那么你就不能用 <code class="FUNCTION">palloc</code> 分配返回的对象，至少是不能在你已经和 SPI 连接上的时候。如果你试图这么做，那么该对象将在 <code class="FUNCTION">SPI_finish</code>的时候被释放，因而你的过程就不能可靠地工作了!要解决这个问题，使用 <code class="FUNCTION">SPI_palloc</code> 分配你的返回对象。<code class="FUNCTION">SPI_palloc</code> 从"上层执行者环境"中分配空间，也就是调用 <code class="FUNCTION">SPI_connect</code> 时候的当前环境内存环境，该环境是从你的过程返回数值的正确环境。</p>
<p>如果还没有连接到 SPI 的时候调用它，<code class="FUNCTION">SPI_palloc</code> 的行为和简单的 <code class="FUNCTION">palloc</code> 一样。在一个过程和 SPI 管理器连接之前，当前的内存环境是上层执行者环境，因此所有该过程使用 <code class="FUNCTION">palloc</code> 或者 SPI 工具函数分配的空间都是在这个环境中分配的。</p>
<p>在调用 <code class="FUNCTION">SPI_connect</code> 之后，当前环境是该过程私有的，由 <code class="FUNCTION">SPI_connect</code> 制作的环境。所有通过 <code class="FUNCTION">palloc</code>, <code class="FUNCTION">repalloc</code> 或者 SPI 工具函数(除了 <code class="FUNCTION">SPI_copytuple</code>, <code class="FUNCTION">SPI_returntuple</code>, <code class="FUNCTION">SPI_modifytuple</code>, <code class="FUNCTION">SPI_palloc</code>)分配的内存都是在这个环境中分配的。如果一个过程与 SPI 管理器断开(通过 <code class="FUNCTION">SPI_finish</code>)，那么当前环境恢复为上层执行器环境，并且所有在该过程的内存环境中分配的内存都释放掉并且不能再次使用！</p>
<p>所有在本节内描述的函数都可以在已连接的和未连接的过程中使用。在未连接的过程中，他们的行为和下层的原始后端函数(<code class="FUNCTION">palloc</code> 等)相同。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="spi-spi-getnspname.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="spi-spi-palloc.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">SPI_getnspname</td><td width="34%" align="center" valign="top"><a href="spi.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">SPI_palloc</td></tr>
</table>
</div>
</body></html>